﻿using CodePlex.TfsPluginSuite.Configuration;
using CodePlex.TfsPluginSuite.Helper;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Framework.Server;
using Microsoft.TeamFoundation.VersionControl.Common;
using Microsoft.TeamFoundation.VersionControl.Server;
using System;

namespace CodePlex.TfsPluginSuite.Notifications
{
    public class BranchSecurityInheritOnly : ISubscriber
    {
        public string Name => typeof(BranchSecurityInheritOnly).FullName;
        public SubscriberPriority Priority => SubscriberPriority.Normal;

        public EventNotificationStatus ProcessEvent(IVssRequestContext requestContext,
            NotificationType notificationType,
            object notificationEventArgs,
            out int statusCode,
            out string statusMessage,
            out ExceptionPropertyCollection properties)
        {
            properties = new ExceptionPropertyCollection();
            statusMessage = String.Empty;
            statusCode = 0;

            bool branched = false;

            // If this is a Check-in notification and is a decision point
            if (notificationEventArgs is CheckinNotification
                && notificationType == NotificationType.Notification
                && TfsPluginSuiteConfigurationManager.Section.BranchMergePolicy.SetBranchSecurityToInheritOnly)
            {
                try
                {
                    CheckinNotification notification = notificationEventArgs as CheckinNotification;
                    if (notification.CheckinType == CheckinType.Branch)
                    {
                        branched = true;
                    }
                    //evaluate non-first class branches
                    else if (notification.CheckinType == CheckinType.Workspace)
                    {
                        using (var tfsHelper = new TfsHelper(requestContext, notification))
                        {
                            foreach (var change in tfsHelper.GetChanges())
                            {
                                var changeType = (ChangeType)change.ChangeEx;
                                //evaluate for folder branch
                                if (changeType.HasFlag(ChangeType.Branch))
                                {
                                    branched = true;
                                }
                            }
                        }
                    }
                    if (branched)
                    {
                        var securityService = requestContext.GetService<TeamFoundationSecurityService>();
                        var vcSecurity = securityService.GetSecurityNamespace(requestContext, SecurityConstants.RepositorySecurityNamespaceGuid);
                        //remove explicit TFS source control permissions on new branch
                        vcSecurity.RemoveAccessControlLists(requestContext, notification.GetSubmittedItems(requestContext), true);
                    }
                }
                catch (Exception e)
                {
                    statusCode = -1;
                    statusMessage += e.ToString();
                    requestContext.Status = e;
                }
            }
            return EventNotificationStatus.ActionPermitted;
        }

        public Type[] SubscribedTypes()
        {
            return new Type[] { typeof(CheckinNotification) };
        }
    }
}
